package cn.com.oceansoft.modules.members.controller;

import cn.com.oceansoft.application.Constant;
import cn.com.oceansoft.application.constant.ConfigInfo;
import cn.com.oceansoft.application.websocket.Constants;
import cn.com.oceansoft.application.websocket.TextMessageHandler;
import cn.com.oceansoft.application.common.util.HttpClientUtil;
import cn.com.oceansoft.framework.kits.ApiResult;
import cn.com.oceansoft.framework.kits.ExecutorKit;
import cn.com.oceansoft.framework.kits.QRCodeKit;
import cn.com.oceansoft.framework.kits.RSAUtils;
import cn.com.oceansoft.modules.cache.service.BaseCacheService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.security.KeyPair;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * Created by zhangxh on 2016/10/3.
 */
@Controller
@RequestMapping("members")
public class MemberController {


    @Resource
    private BaseCacheService cacheService;
    @Resource
    protected ConfigInfo configInfo;
    @Bean
    public TextMessageHandler textMessageHandler() {
        return new TextMessageHandler();
    }

    @ModelAttribute
    public void initKey(HttpServletRequest request,Model model){
        KeyPair keyPair= (KeyPair) request.getSession().getAttribute(Constant.KEY_PAIR);
        if(keyPair==null){
            try {
                RSAUtils.KEY_PAIR=RSAUtils.generateKeyPair();
                request.getSession().setAttribute(Constant.KEY_PAIR,RSAUtils.KEY_PAIR);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            RSAUtils.KEY_PAIR=keyPair;
        }
        //返回n和e到页面上，有这两个值就能得出公钥
        request.getSession().setAttribute("n", RSAUtils.getModulus());
        request.getSession().setAttribute("e", RSAUtils.getPublicExponent());
    }
    @RequestMapping(value = "login",method = RequestMethod.GET)
    public String toLogin(Model model, HttpServletRequest request){
        String returnUrl=request.getParameter("return_url");
        if(!StringUtils.isEmpty(returnUrl)){
            model.addAttribute("return_url",returnUrl);
        }
        return "members/to_login";
    }
    @ResponseBody
    @RequestMapping(value = "login",method = RequestMethod.POST)
    public ApiResult login(@RequestBody Map map,HttpServletRequest request){

        String password= (String) map.get("password");
        if(StringUtils.isEmpty(password)){
            return new ApiResult(false,10400,"请输入密码",null);
        }
        try {
            String decryptResult = RSAUtils.decryptPrivate(password);
            map.put("password",decryptResult);
        } catch (Exception e) {
            e.printStackTrace();
            return new ApiResult(false,10400,"服务器异常",null);
        }
        String result=HttpClientUtil.doPostString(configInfo.getMsHostUrl()+"members/login",map);
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
        if(apiResult.isSucc()){
            request.getSession().setAttribute(Constant.CURRENT_MEMBER,apiResult.getData());
        }
        return apiResult;
    }

    @RequestMapping("to_register")
    public String toRegister(){
        return "members/to_register";
    }
    @RequestMapping("to_update")
    public String update(){
        return "members/to_update";
    }
    @RequestMapping("to_forget_pwd")
    public String toForgetPWD(){
        return "members/to_forget_pwd";
    }
    @ResponseBody
    @RequestMapping(method = RequestMethod.POST)
    public ApiResult post(@RequestBody Map map, HttpServletRequest request){
        String source= (String) map.get("source");
        String code= (String) map.get("code");
        map.remove("source");
        map.remove("code");
        String sms_code= (String) request.getSession().getAttribute(source);
        if(sms_code==null||!sms_code.equals(code)){
            return new ApiResult(false, 10005,"验证码不正确",null);
        }
        String password= (String) map.get("password");
        if(StringUtils.isEmpty(password)){
            return new ApiResult(false,10400,"请输入密码",null);
        }
        try {
            String decryptResult = RSAUtils.decryptPrivate(password);
            map.put("password",decryptResult);
        } catch (Exception e) {
            e.printStackTrace();
            return new ApiResult(false,10400,"服务器异常",null);
        }

        String result=HttpClientUtil.doPostString(configInfo.getMsHostUrl()+"/members",map);
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
        if(apiResult.isSucc()){
            request.getSession().setAttribute(Constant.CURRENT_MEMBER,apiResult.getData());
        }
        return apiResult;
    }
    @ResponseBody
    @RequestMapping(value = "login_out",method = RequestMethod.POST)
    public ApiResult loginOut( HttpServletRequest request){
        request.getSession().invalidate();
        return new ApiResult();
    }
    @RequestMapping(value="to_scan_qrcode",method = RequestMethod.GET)
    @ResponseBody
    public ApiResult toScanQRcode(HttpServletRequest request){
        String uuid = UUID.randomUUID().toString();
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
        String url=basePath+"/members/to_scan_login/"+uuid;
        System.out.println(url);
        String base64 = QRCodeKit.toBase64(url, 200, 200);
        request.getSession().setAttribute(Constants.DEFAULT_WEBSOCKET_USERNAME,uuid);//存uuid做为websocket的通讯用
        request.getSession().setAttribute("timeout",false);//判断是否超时
        Date start=new Date();
        HttpSession session=request.getSession();
        ExecutorKit.execute(new Runnable() {
            @Override
            public void run() {
                while(new Date().getTime()-60*1000<start.getTime()){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                WebSocketSession wss=textMessageHandler().getSession(uuid);
                if(wss!=null) {
                    textMessageHandler().getSession(uuid).getAttributes().put("timeout", true);
                    textMessageHandler().sendMessageToUser(uuid, new TextMessage("timeout"));
                }
            }
        });
        return new ApiResult(true,10200,"",base64);
    }
    @RequestMapping(value="to_scan_login/{uuid}",method = RequestMethod.GET)
    public String toScanLogin(@PathVariable("uuid") String uuid, Model model){
        model.addAttribute("uuid",uuid);
        return "members/to_scan_login";
    }
    @RequestMapping(value="scan_login",method = RequestMethod.POST)
    @ResponseBody
    public ApiResult scanLogin(HttpServletRequest request){
        String accountId=request.getParameter("accountId");
        String password=request.getParameter("password");
        if(StringUtils.isEmpty(password)){
            return new ApiResult(false,10400,"请输入密码",null);
        }
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("acountId",accountId);
        try {
            String decryptResult = RSAUtils.decryptPrivate(password);
            map.put("password",decryptResult);
        } catch (Exception e) {
            e.printStackTrace();
            return new ApiResult(false,10400,"服务器异常",null);
        }
        String result = HttpClientUtil.doPostString(configInfo.getMsHostUrl() + "/members/login", map);
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
        if(apiResult.isSucc()){
            request.getSession().setAttribute(Constant.CURRENT_MEMBER,apiResult.getData());
        }
        return apiResult;
    }
    @RequestMapping(value="confirm_login",method = RequestMethod.POST)
    @ResponseBody
    public ApiResult confirmLogin(HttpServletRequest request){
        String uuid=request.getParameter("uuid");
        WebSocketSession session=textMessageHandler().getSession(uuid);
        if(session!=null){
            Object obj=session.getAttributes().get("timeout");
            if(obj!=null){
                boolean timeout= (boolean) obj;
                if(timeout){
                    return new ApiResult(false,10400,"二维码已失效,请刷新二维码重新扫描",null);
                }
            }
        }
        Object user=request.getSession().getAttribute(Constant.CURRENT_MEMBER);
        if(user!=null){
            HttpSession httpSession= (HttpSession) session.getAttributes().get(HttpSession.class.getName());
            httpSession.setAttribute(Constant.CURRENT_MEMBER,user);
            textMessageHandler().sendMessageToUser(uuid,new TextMessage("success"));
        }else{
            return new ApiResult(false,10400,"确认失败",null);
        }
        return new ApiResult();
    }
    @RequestMapping(value = "sms_code",method = RequestMethod.GET)
    @ResponseBody
    public ApiResult sms_code(@RequestParam("phone") String phone,@RequestParam("source") String source, HttpServletRequest request){
        String sms_code=cacheService.get("sms:code:"+source+":"+request.getSession().getId());
        if(!StringUtils.isEmpty(sms_code)){
            return new ApiResult(false, 10400, "120秒内不能重复获取", null);
        }else{
            String result=HttpClientUtil.doGet(configInfo.getMsHostUrl()+"/members/sms_code","phone",phone);
            ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
            sms_code= (String) apiResult.getData();
            cacheService.set("sms:code:"+source+":"+request.getSession().getId(),sms_code,120);
            request.getSession().setAttribute(source,sms_code);
        }
        //FIXME 测试,返回前台
        return new ApiResult(true, 10200, "", sms_code);
    }
    @RequestMapping(value = "validate",method = RequestMethod.POST)
    @ResponseBody
    public ApiResult validate(@RequestParam("code") String code,@RequestParam("phone") String phone,@RequestParam("source") String source, HttpServletRequest request){
        //FIXME 后续添加验证次数限制
        String sms_code= (String) request.getSession().getAttribute(source);
        if(!sms_code.equals(code)){
            return new ApiResult(false, 10005,"验证码不正确",null);
        }
        ApiResult apiResult=null;
        String result= null;
        result = HttpClientUtil.doGet(configInfo.getMsHostUrl()+"/members/account/"+phone);
        apiResult = JSONObject.parseObject(result, ApiResult.class);

        if(apiResult.getData()==null){
                return new ApiResult(false, 10004,"不存在此用户",null);
            }
        return new ApiResult(true, 10200,"",apiResult.getData());
    }
    @RequestMapping(value = "{id}/password",method = RequestMethod.POST)
    @ResponseBody
    public ApiResult password(@PathVariable String id, @RequestParam String password, HttpServletRequest request){
        if(StringUtils.isEmpty(password)){
            return new ApiResult(false,10400,"请输入密码",null);
        }
        Map map=new HashMap();
        try {
            String decryptResult = RSAUtils.decryptPrivate(password);
            map.put("password",decryptResult);
        } catch (Exception e) {
            e.printStackTrace();
            return new ApiResult(false,10400,"服务器异常",null);
        }
        String result=HttpClientUtil.doTransfer(new HttpPost(configInfo.getMsHostUrl()+"/members/"+id+"/password"),map, ContentType.APPLICATION_FORM_URLENCODED);
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
        return apiResult;
    }


    /**
     * 附件上传，
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "pic/att", method = RequestMethod.POST)
    public ApiResult postHeadPic(MultipartHttpServletRequest request) throws Exception {

        MultipartFile mp = request.getFile("materialFile");
        String orifileName = mp.getOriginalFilename();

        File file = new File(orifileName);
        try {
            FileUtils.writeByteArrayToFile(file, mp.getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        }

        BASE64Encoder encode =new BASE64Encoder();
        String data = encode.encode(mp.getBytes());

        Map mp_current_member = (Map) request.getSession().getAttribute(Constant.CURRENT_MEMBER);
        String result = HttpClientUtil.uploadFile(configInfo.getMsHostUrl() + "/members/"+mp_current_member.get("guid")+"/att", file);
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
        apiResult.setData(data);
        file.delete();
        return ApiResult.succ(apiResult);
    }



    /**
     * 更新用户信息
     * @param map
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "user", method = POST)
    public ApiResult saveUser(HttpServletRequest request, @RequestBody Map map) {


        Map mp_current_member = (Map) request.getSession().getAttribute(Constant.CURRENT_MEMBER);

        String result = HttpClientUtil.doPatch(configInfo.getMsHostUrl() + "/members/"+mp_current_member.get("guid"), map,ContentType.APPLICATION_JSON );
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);

        return apiResult;
    }

    /**
     * 账号注销
     * @param request
     * @param map
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "logoff", method = POST)
    public ApiResult logoff(HttpServletRequest request, @RequestBody Map map) {
        String source= (String) map.get("source");
        String code= (String) map.get("code");
        map.remove("source");
        map.remove("code");
        String sms_code= (String) request.getSession().getAttribute(source);
        if(sms_code==null||!sms_code.equals(code)){
            return new ApiResult(false, 10005,"验证码不正确",null);
        }
        String password= (String) map.get("password");
        if(StringUtils.isEmpty(password)){
            return new ApiResult(false,10400,"请输入密码",null);
        }
        Map currentUser= (Map) request.getSession().getAttribute(Constant.CURRENT_MEMBER);
        if(currentUser==null||!currentUser.get("idNum").equals(map.get("idNum"))){
            return new ApiResult(false,10400,"身份证号码不正确",null);
        }
        try {
            String decryptResult = RSAUtils.decryptPrivate(password);
            map.put("password",decryptResult);
        } catch (Exception e) {
            e.printStackTrace();
            return new ApiResult(false,10400,"服务器异常",null);
        }
        String result = HttpClientUtil.doPostString(configInfo.getMsHostUrl() + "/members/logoff", map);
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);
        if(apiResult.isSucc()){
            request.getSession().invalidate();
        }
        return apiResult;
    }



    /**
     * 更新用户信息
     * @param map
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "comp", method = POST)
    public ApiResult saveQy(HttpServletRequest request, @RequestBody Map map) {


        Map mp_current_member = (Map) request.getSession().getAttribute(Constant.CURRENT_MEMBER);

        String result = HttpClientUtil.doPatch(configInfo.getMsHostUrl() + "/comps/"+mp_current_member.get("guid"), map,ContentType.APPLICATION_JSON );
        ApiResult apiResult = JSONObject.parseObject(result, ApiResult.class);

        return apiResult;
    }

}
